#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#include "modbus.h"
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <signal.h>
#include <errno.h>
#include <sys/msg.h>
#include <stdint.h>
#include <arpa/inet.h> // 用于字节序转换

// 共享内存数据结构
typedef union equipment {
   bool a;
    int b;
    double d; // 修改为double类型
} Equipment;

// 修改后的共享内存结构体定义
typedef struct shm_modbus {
    int key;

    int type; // 1=bool, 2=int, 3=double
    int addr; 
    Equipment val;
} Shm_Modbus;

// 消息队列结构
struct msgbuf {
    long mtype;
    int num1;
    int num2;
    int num3;
    int num4;
};

// 全局变量
modbus_t *ctx;
int shm_id = -1;
Shm_Modbus* shared_items = NULL;
int sensor_count = 6; // 人流量、温度 + 4个开关
void* shm_addr = NULL;
volatile sig_atomic_t keep_running = 1;
int msgid = -1; // 消息队列ID

// 信号处理函数
void sigint_handler(int sig) {
    keep_running = 0;
}




double convert_float(uint16_t reg1, uint16_t reg2) {
    // 将两个16位寄存器组合为32位整数
    uint32_t combined = ((uint32_t)reg1 << 16) | reg2;
    
    // 将32位整数转换为浮点数
    float result;
    memcpy(&result, &combined, sizeof(float));
    
    return (double)result;
}

// 数据采集线程
// 3. 修改数据采集线程
void *read_data(void *arg) {
    uint16_t reg[3]; // 读取5个寄存器
    
    while (keep_running) {
        modbus_set_slave(ctx, 2);
        int rc = modbus_read_registers(ctx, 0, 3, reg);
        
        if (rc != 3) {
            usleep(100000);
            continue;
        }

        // 使用寄存器1-4计算温度值
        double temperature = convert_float(reg[1], reg[2]); 
        // 更新共享内存
        if (shared_items) {
            shared_items[0].val.b = reg[0]; // 人流量
            shared_items[4].val.d = temperature;    // 空调温度
        }
        
        usleep(500000);
    }
    return NULL;
}

// 打印线程
void *print_shared_memory(void *arg) {
    while (keep_running) {
        // 打印共享内存数据
        printf("\n===== 共享内存数据 =====\n");
        
        // 遍历所有设备
        for (int i = 0; i < sensor_count; i++) {
            printf("设备 %d ,(Key=%d): ", i, shared_items[i].key);
            
            // 根据类型打印值
            switch (shared_items[i].type) {
                case 1: // bool
                    printf("%s", shared_items[i].val.a ? "开启" : "关闭");
                    break;
                case 2: // int
                    printf("%d", shared_items[i].val.b);
                    break;
                case 3: // double
                    printf("%.1f°C", shared_items[i].val.d); // 使用%.1f格式打印double
                    break;
                default:
                    printf("未知类型");
            }
            printf("\n");
        }
        
        printf("======================\n");
        
        // 固定延迟1秒
        sleep(1);
    }
    return NULL;
}

// 消息处理线程
void *process_messages(void *arg) {
    size_t s = sizeof(struct msgbuf) - sizeof(long);
    struct msgbuf buf;
    int command_count = 0;
    
    while (keep_running) {
        // 接收消息
        if (msgrcv(msgid, &buf, s, 1, IPC_NOWAIT) < 0) {
            usleep(100000); // 100ms检查一次
            continue;
        }
        
        command_count++;
        printf("\n[指令接收] 命令#%d: %d %d %d %d\n", 
               command_count, buf.num1, buf.num2, buf.num3, buf.num4);
        
        // 更新共享内存中的开关状态
        if (shared_items) {
            shared_items[1].val.a = buf.num1; // 门开关 (bool)
            shared_items[2].val.a = buf.num2; // 窗户开关 (bool)
            shared_items[3].val.a = buf.num3; // 空调开关 (bool)
            shared_items[5].val.a = buf.num4; // 风扇开关 (bool)
        }
        
        // 控制Modbus设备
        modbus_set_slave(ctx, 1);
        modbus_write_bit(ctx, 1, buf.num1); // 门控制
        modbus_write_bit(ctx, 2, buf.num2); // 窗控制
        modbus_write_bit(ctx, 3, buf.num3); // 空调开关
        modbus_write_bit(ctx, 4, buf.num4); // 风扇控制
        
        printf("设备控制完成。\n");
    }
    return NULL;
}

// 初始化消息队列
int init_message_queue() {
    key_t key = ftok("/tmp/ipc/msgqueue/peer/modbus", 'j');
    int msgid = msgget(key, IPC_CREAT | 0666);
    return msgid;
}

int main(int argc, char const *argv[]) {
    signal(SIGINT, sigint_handler);
    
    pthread_t data_thread, print_thread, msg_thread;
    
    // 创建消息队列
    msgid = init_message_queue();
    if (msgid == -1) {
        perror("消息队列创建失败");
        return 1;
    }
    
    // 创建共享内存区域
    key_t shm_key = ftok("/tmp/ipc/shmem/modbus", 'j');
     size_t shm_size = 1024; // 固定1024字节
    shm_id = shmget(shm_key, shm_size, IPC_CREAT | 0666);
    if (shm_id == -1) {
        perror("shmget失败");
        return 1;
    }
    
    shm_addr = shmat(shm_id, NULL, 0);
    if (shm_addr == (void*)-1) {
        perror("shmat失败");
        return 1;
    }
    
    // 初始化共享内存布局
    int* count_ptr = (int*)shm_addr;
    *count_ptr = sensor_count;
    
    shared_items = (Shm_Modbus*)(count_ptr + 1);
    
    // 初始化共享内存项
    // 人流量 - int类型 (type=2)
    shared_items[0].key = 101;
    shared_items[0].type = 2; // int
    shared_items[0].addr = 40001; 
    shared_items[0].val.b = 0; // 初始化
    
    
    // 门开关 - bool类型 (type=1)
    shared_items[1].key = 102;
    shared_items[1].type = 1; // bool
    shared_items[1].addr = 10001; 
    shared_items[1].val.a = false; // 初始化关闭
    
    // 窗户开关 - bool类型 (type=1)
    shared_items[2].key = 103;
    shared_items[2].type = 1; // bool
    shared_items[2].addr = 10002; 
    shared_items[2].val.a = false; // 初始化关闭
    
    // 空调开关 - bool类型 (type=1)
    shared_items[3].key = 104;
    shared_items[3].type = 1; // bool
    shared_items[3].addr = 10003; 
    shared_items[3].val.a = false; // 初始化关闭
     // 空调温度 - double类型 (type=3)
    shared_items[4].key = 105;
    shared_items[4].type = 3; // 设置为double类型
    shared_items[4].addr = 40002; 
    shared_items[4].val.d = 0.0; // 初始化为0.0
    
    // 风扇开关 - bool类型 (type=1)
    shared_items[5].key = 106;
    shared_items[5].type = 1; // bool
    shared_items[5].addr = 10004; 
    shared_items[5].val.a = false; // 初始化关闭
    
    ctx = modbus_new_tcp("192.168.50.183", 502);
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Modbus连接失败: %s\n", modbus_strerror(errno));
        return 1;
    }
    
    printf("Modbus连接成功! 开始创建线程...\n");
    
    // 创建数据采集线程
    pthread_create(&data_thread, NULL, read_data, NULL);
    
    // 创建共享内存打印线程
    pthread_create(&print_thread, NULL, print_shared_memory, NULL);
    
    // 创建消息处理线程
    pthread_create(&msg_thread, NULL, process_messages, NULL);
    
    printf("系统初始化完成。按Ctrl+C退出...\n");
    
    // 主线程等待退出信号
    while (keep_running) {
        pause(); // 暂停等待信号
    }

    // 安全退出处理
    pthread_cancel(data_thread);
    pthread_cancel(print_thread);
    pthread_cancel(msg_thread);
    pthread_join(data_thread, NULL);
    pthread_join(print_thread, NULL);
    pthread_join(msg_thread, NULL);
    
    if (ctx) {
        modbus_close(ctx);
        modbus_free(ctx);
    }
    
    // 清理消息队列
    if (msgid >= 0) {
        msgctl(msgid, IPC_RMID, NULL);
    }
    
    // 清理共享内存
    if (shm_id >= 0) {
        shmdt(shm_addr);
        shmctl(shm_id, IPC_RMID, NULL);
    }
    
    return 0;
}  